// run: $exec < input
#include <iostream>
#include <algorithm>
#include <vector>

struct edge
{
	int from, to, cost;
};

bool operator<(edge const & a, edge const & b)
{
	return a.cost < b.cost;
}

struct query
{
	int lim;
	int index;
};

bool operator<(query const & a, query const & b)
{
	return a.lim < b.lim;
}

int const maxn = 20007;
int const maxq = 5007;
int const maxm = 100007;

std::vector<edge> input_edge(maxm);
std::vector<query> input_query(maxq);
int n, m, q;

long long tmp_ans;

int father[maxn];
int rank[maxn];
int tot[maxn];
long long ans[maxq];

int color_num[maxn];

long long get_two(long long x)
{
	return x * (x - 1);
}

int getfather(int x)
{
	return (x == father[x] ? x : father[x] = getfather(father[x]));
}

void set_union(int x, int y)
{
	int tx = getfather(x);
	int ty = getfather(y);
	if (tx != ty) {
		tmp_ans += tot[tx] * tot[ty] * 2;
		if (rank[tx] > rank[ty]) {
			father[ty] = tx;
			tot[tx] += tot[ty];
		}
		else {
			father[tx] = ty;
			tot[ty] += tot[tx];
			if (rank[tx] == rank[ty])
				rank[ty]++;
		}
	}
}

int main()
{
	int T;
	std::cin >> T;
	while (T--) {
		std::cin >> n >> m >> q;
		tmp_ans = 0;
		for (int i = 0; i < m; i++)
			std::cin >> input_edge[i].from >> input_edge[i].to >> input_edge[i].cost;
		std::sort(input_edge.begin(), input_edge.end());

		for (int i = 0; i < q; i++) {
			std::cin >> input_query[i].lim;
			input_query[i].index = i;
		}
		std::sort(input_query.begin(), input_query.end());

		for (int i = 0; i < n; i++) { father[i] = i; rank[i] = 1; }

		int qi = 0;
		for (int i = 0; i < m; i++) {
			while (input_query[qi].lim < input_edge[i].cost) {
				ans[input_query[qi].index] = tmp_ans;
				qi++;
			}
			set_union(input_edge[i].from, input_edge[i].to);
		}

		for (int i = 0; i < q; i++)
			std::cout << ans[i] << '\n';
	}
}

